package cn.com.flower.passport.filter;

import cn.com.flower.common.enumerator.ServiceCode;
import cn.com.flower.common.pojo.authentication.CurrentPrincipal;
import cn.com.flower.common.pojo.po.UserCachePO;
import cn.com.flower.common.web.JsonResult;
import cn.com.flower.passport.dao.cache.IUserCacheRepository;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {

    @Value("${flower..jwt.secret-key}")
    private String secretKey;
    @Autowired
    private IUserCacheRepository iUserCacheRepository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        // 不需要使用JWT认证的放行给下个过滤器
        if (requestURI.equals("/users/login")
                || requestURI.endsWith(".css")
                || requestURI.endsWith(".js")
                || requestURI.equals("/doc.html")) {
            // 放行给下个过滤器
            filterChain.doFilter(request, response);
            return;
        }


        System.out.println("处理JWT的过滤器开始处理请求：" + requestURI);

        String jwt = request.getHeader("Authorization");
        System.out.println("客户端携带的JWT：" + jwt);

        // 如果客户端未携带jwt放行给下个过滤器
        if (jwt == null) {
            filterChain.doFilter(request, response);
            return;
        }

        // 尝试解析jwt
        Claims claims = null;

        // 处理解析jwt的异常
        try {
            claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();
        } catch (MalformedJwtException e) {
            response.setContentType("application/json; charset=UTF-8");
            String message = "你妈了逼给爷滚!";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            return;
        } catch (SignatureException e) {
            response.setContentType("application/json; charset=UTF-8");
            String message = "你妈了逼给爷滚!";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            return;
        } catch (Throwable e) {
            response.setContentType("application/json; charset=UTF-8");
            String message = "服务器繁忙，请稍后尝试!";
            logger.warn("", e);
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNKNOWN, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            return;
        }

        // 获取jwt的数据
        Long userId = claims.get("id", Long.class);
        String username = claims.get("username", String.class);
        String remoteAddr = claims.get("remoteAddr", String.class);
        String userAgent = claims.get("userAgent", String.class);
        System.out.println("解析JWT的结果：userId = " + userId);
        System.out.println("解析JWT的结果：username = " + username);
        System.out.println("解析JWT的结果：remoteAddr = " + remoteAddr);
        System.out.println("解析JWT的结果：userAgent = " + userAgent);

        // 检查是否盗用
        String currentRemoteAddr = request.getRemoteAddr();
        String currentUserAgent = request.getHeader("User-Agent");
        if (!currentRemoteAddr.equals(remoteAddr) && !currentUserAgent.equals(userAgent)) {
            System.out.println("ip或浏览器信息异常!");
            filterChain.doFilter(request, response);
            return;
        }

        // 获取此用户在redis中的数据
        UserCachePO userCachePO = iUserCacheRepository.getUserState(userId);
        System.out.println(userCachePO);
        if (userCachePO == null) {
            filterChain.doFilter(request, response);
        }
        if (userCachePO.getEnable() != 1) {
            response.setContentType("application/json; charset=UTF-8");
            String message = "您的帐号状态异常, 将强制下线!";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            // 删除用户状态数据
            iUserCacheRepository.deleteUserState(userId);
            return;
        }

        // 续期
        iUserCacheRepository.renewal(userId);

        // 创建Security框架用的当事人
        Object principal = new CurrentPrincipal(userId, username);

        // 创建Security框架将使用到的权限列表
        // 从用户状态中获取权限信息的JSON字符串
        String authoritiesJsonString = userCachePO.getAuthoritiesJsonString();
        // 将JSON字符串转换为List
        List<String> stringList = JSON.parseArray(authoritiesJsonString, String.class);
        // 创建一个空的权限集合
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        // 遍历权限字符串列表，将每个权限字符串转换为SimpleGrantedAuthority对象，并添加到权限集合中
        for (String s : stringList) {
            authorities.add(new SimpleGrantedAuthority(s));
        }

        // 向SecurityContext中存入Authentication数据
        Authentication authentication = new UsernamePasswordAuthenticationToken(principal, null, authorities);
        // 获取当前的Security上下文
        SecurityContext securityContext = SecurityContextHolder.getContext();
        // 将创建的Authentication对象设置到Security上下文中
        securityContext.setAuthentication(authentication);

        // 放行
        filterChain.doFilter(request, response);
    }
}
